package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"golang.org/x/sync/errgroup"
)

// VideoResponse 定义从 API 返回的数据结构
type VideoResponse struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Data struct {
		Video string `json:"video"`
	} `json:"data"`
}

func main() {
	// 检查命令行参数
	if len(os.Args) != 2 {
		fmt.Println("Usage: go run main.go <number_of_requests>")
		return
	}

	// 获取命令行参数
	n, err := strconv.Atoi(os.Args[1])
	if err != nil || n <= 0 {
		fmt.Println("Invalid number of requests. Please provide a positive integer.")
		return
	}

	// 定义 API URL
	apiURL := "https://api.52vmy.cn/api/video/tianmei"

	// 创建缓存文件夹
	cacheFolder := "video_cache"
	err = os.MkdirAll(cacheFolder, os.ModePerm)
	if err != nil {
		fmt.Println("Error creating cache folder:", err)
		return
	}

	// 创建下载目录
	downloadFolder := "downloaded_videos"
	err = os.MkdirAll(downloadFolder, os.ModePerm)
	if err != nil {
		fmt.Println("Error creating download folder:", err)
		return
	}

	// 使用 errgroup 管理协程
	var group errgroup.Group

	// 并发发送 GET 请求并缓存链接
	for i := 1; i <= n; i++ {
		index := i
		group.Go(func() error {
			videoURL, err := getVideoURL(apiURL)
			if err != nil {
				return fmt.Errorf("error fetching video URL: %w", err)
			}

			// 缓存链接到本地文件
			linkFilePath := filepath.Join(cacheFolder, fmt.Sprintf("link_%d.txt", index))
			err = os.WriteFile(linkFilePath, []byte(videoURL), 0644)
			if err != nil {
				return fmt.Errorf("error saving link to file: %w", err)
			}
			fmt.Println("Link cached successfully:", linkFilePath)
			return nil
		})
	}

	// 等待所有协程完成
	if err := group.Wait(); err != nil {
		fmt.Println("Error during caching:", err)
		return
	}

	// 并发下载视频
	files, err := os.ReadDir(cacheFolder)
	if err != nil {
		fmt.Println("Error reading cache folder:", err)
		return
	}

	var downloadGroup errgroup.Group
	for _, file := range files {
		linkFilePath := filepath.Join(cacheFolder, file.Name())
		downloadGroup.Go(func() error {
			linkData, err := os.ReadFile(linkFilePath)
			if err != nil {
				return fmt.Errorf("error reading link file: %w", err)
			}
			videoURL := strings.TrimSpace(string(linkData))
			if videoURL == "" {
				return fmt.Errorf("empty link in file: %s", linkFilePath)
			}

			// 下载视频
			videoFolder := filepath.Join(downloadFolder, strings.TrimSuffix(file.Name(), filepath.Ext(file.Name())))
			err = os.MkdirAll(videoFolder, os.ModePerm)
			if err != nil {
				return fmt.Errorf("error creating video folder: %w", err)
			}

			videoFilePath := filepath.Join(videoFolder, "video.mp4")
			err = downloadVideo(videoURL, videoFilePath)
			if err != nil {
				return fmt.Errorf("error downloading video from %s: %w", videoURL, err)
			}
			fmt.Println("Video downloaded successfully:", videoFilePath)
			return nil
		})
	}

	// 等待所有下载完成
	if err := downloadGroup.Wait(); err != nil {
		fmt.Println("Error during downloading:", err)
	}
}

// 获取视频链接
func getVideoURL(apiURL string) (string, error) {
	resp, err := http.Get(apiURL)
	if err != nil {
		return "", fmt.Errorf("HTTP request failed: %w", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("failed to read response body: %w", err)
	}

	// 打印原始响应内容以便调试
	fmt.Println("Response Body:", string(body))

	var videoResponse VideoResponse
	err = json.Unmarshal(body, &videoResponse)
	if err != nil {
		return "", fmt.Errorf("failed to unmarshal JSON: %w", err)
	}

	if videoResponse.Code != 200 {
		return "", fmt.Errorf("API error: %s", videoResponse.Msg)
	}

	return videoResponse.Data.Video, nil
}

// 下载视频
func downloadVideo(videoURL, filePath string) error {
	resp, err := http.Get(videoURL)
	if err != nil {
		return fmt.Errorf("HTTP request failed: %w", err)
	}
	defer resp.Body.Close()

	file, err := os.Create(filePath)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	_, err = io.Copy(file, resp.Body)
	if err != nil {
		return fmt.Errorf("failed to download video: %w", err)
	}
	return nil
}
